﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AxSLIDERLib;

namespace IntelliTouchMix
{
    public enum OrderType { 
        ASC,
        DESC
    }

    class UIController
    {
        public frmMain formMain;

        public int trackBarOneShotSteps = 10;
        public int trackBarRealTimeSteps = 1;
        public int deviceMaxPixelHeight = 13;
        public int deviceMaxPixelWidth = 15;
        public int deviceMaxPixelDiagonal = 0;
        public double callibrateMaxDistanceTolerancePercentage = 50;
        public double deviceMaxHorizontalDistance = 0;
        public double deviceMaxVerticalDistance = 0;
        public double deviceMaxDiagonalDistance = 0;
        public double deviceMaxHorizontalVelocity = 0;
        public double deviceMaxVerticalVelocity = 0;
        public double deviceMaxDiagonalVelocity = 0;
        public double callibrateMaxContinueVelocityTolerancePercentage = 90;
        public double deviceMaxOneShotHorizontalVelocity = 0;
        public double deviceMaxOneShotVerticalVelocity = 0;
        public double deviceMaxOneShotDiagonalVelocity = 0;
        public double callibrateMaxStartVelocityTolerancePercentage = 0;
        public double callibrateRealTimeStepRound = 0.5;
        public double deviceRefreshRealTimePeriod = Util.reportTimeLimit;
        public double callibrateMillisecondsOneShot = Util.oneShotTimeLimit;
        public double tempDistanceInit = 0;
        public double tempDistanceStart = 0;
        public double maxDistance = 0;


        public UIController(frmMain formMain)
        {
            this.formMain = formMain;
            loadConfig();
            deviceMaxPixelDiagonal = (int)Math.Sqrt(deviceMaxPixelHeight * deviceMaxPixelHeight + deviceMaxPixelWidth * deviceMaxPixelWidth);
            deviceMaxHorizontalVelocity = deviceMaxPixelWidth / deviceRefreshRealTimePeriod;
            deviceMaxVerticalVelocity = deviceMaxPixelHeight / deviceRefreshRealTimePeriod;
            deviceMaxDiagonalVelocity = deviceMaxPixelDiagonal / deviceRefreshRealTimePeriod;
            deviceMaxOneShotHorizontalVelocity = deviceMaxPixelWidth / callibrateMillisecondsOneShot;
            deviceMaxOneShotVerticalVelocity = deviceMaxPixelHeight / callibrateMillisecondsOneShot;
            deviceMaxOneShotDiagonalVelocity = deviceMaxPixelDiagonal / callibrateMillisecondsOneShot;
            deviceMaxHorizontalDistance = deviceMaxPixelWidth * (1- callibrateMaxDistanceTolerancePercentage/100);
            deviceMaxVerticalDistance = deviceMaxPixelHeight * (1 - callibrateMaxDistanceTolerancePercentage/100);
            deviceMaxDiagonalDistance = deviceMaxPixelDiagonal * (1 - callibrateMaxDistanceTolerancePercentage/100);

        }

        public void loadConfig()
        { 
        }

        public int increaseOrDecreaseLinearValue(TouchMouseEventArgs tmea,int value,int min,int max,int stepOneShot,int stepRealTime,OrderType order)
        {
            return (int)increaseOrDecreaseLinearValue(tmea,(double)value, (double)min, (double)max, (double)stepOneShot,(double)stepRealTime,order);
        }

        public double increaseOrDecreaseLinearValue(TouchMouseEventArgs tmea, double value, double min, double max, double stepOneShot, double stepRealTime,OrderType order)
        {
            SenseType increaseSense = (order == OrderType.ASC ? SenseType.POSITIVE : SenseType.NEGATIVE);
            SenseType decreaseSense = (order == OrderType.ASC ? SenseType.NEGATIVE : SenseType.POSITIVE);
            if (!((value == max && tmea.senseType == increaseSense) || (value == min && tmea.senseType == decreaseSense)))
            {
                double range = max - min;
                if (tmea.eventType == EventType.ONE_SHOT)
                {
                    if (tmea.senseType == increaseSense)
                    {
                        value += stepOneShot;
                    }
                    else
                    {
                        value -= stepOneShot;
                    }
                }
                else
                {
                    switch(tmea.actionType)
                    {
                        case ActionType.START:
                            tempDistanceInit = value;
                            tempDistanceStart = tmea.distance;
                            if(tmea.movementType==MovementType.LINEAR)
                                if (tmea.directionType == DirectionType.LEFT || tmea.directionType == DirectionType.RIGHT)
                                    maxDistance = deviceMaxHorizontalDistance;
                                else
                                    maxDistance = deviceMaxVerticalDistance;
                            else
                                maxDistance = deviceMaxDiagonalDistance;
                            break;
                        case ActionType.CONTINUE:
                            double advance = ((tmea.distance + tempDistanceStart) * range) / maxDistance;
                            double difference = advance / stepRealTime;
                            if ((difference - (int)difference) >= callibrateRealTimeStepRound)
                                advance = ((int)difference + 1) * stepRealTime;
                            else
                                advance = ((int)difference) * stepRealTime;
                            if (tmea.senseType == increaseSense)
                                value += advance;
                            else
                                value -= advance;
                            tempDistanceStart = 0;
                             break;
                    }
                }
                value = value > max ? max : value;
                value = value < min ? min : value;
            }
            return value;
        }

        public int moveItemListBox(ListBox lb,TouchMouseEventArgs tmea)
        {
            int exit = 0;
            lb.Invoke((MethodInvoker)delegate{
            if (lb.Items.Count > 0)
            {
                if (lb.SelectedIndex >= 0)
                {
                    int lastIndex = lb.SelectedIndex;
                    int index = exit = increaseOrDecreaseLinearValue(tmea, lb.SelectedIndex, 0, lb.Items.Count - 1, 1, 1, OrderType.DESC);
                    if (lastIndex != index)
                    {
                        object temp = lb.Items[lastIndex];
                        lb.Items.RemoveAt(lastIndex);
                        lb.Items.Insert(index, temp);
                        lb.SelectedIndex = index;
                    }
                }
                else 
                {
                    lb.SelectedIndex = 0;
                }
            }
            });
            return exit;
        }


        public double controllTrackBar(AxGSlider tb, TouchMouseEventArgs tmea,int steps)
        {
            double exit = -1;
            if (tb!=null)
                tb.Value = exit = increaseOrDecreaseLinearValue(tmea, tb.Value, tb.Min, tb.Max, (tb.Max - tb.Min) / steps, trackBarRealTimeSteps, OrderType.ASC);
            return exit;
        }

        public int controllListBox(ListBox lb, TouchMouseEventArgs tmea)
        {
            int exit = 0;
            lb.Invoke((MethodInvoker)delegate{
            if (lb.Items.Count > 0)
            {
                if (lb.SelectedIndex >= 0)
                {
                    lb.SelectedIndex = exit = increaseOrDecreaseLinearValue(tmea, lb.SelectedIndex, 0, lb.Items.Count - 1, 1, 1, OrderType.DESC);
                }
                else
                {
                    lb.SelectedIndex = 0;
                }
            }
            });
            return exit;
        }

        public double controllWaveScroll(short player, TouchMouseEventArgs tmea)
        {
            double exit = 0;
            formMain.formMain.Invoke((MethodInvoker)delegate{
                formMain.formMain.ManageTouchDownOnScroll(player, tmea);
            });
            return exit;
        }

        

    }
}
